package cn.edu.xjtu.android.emoji_warfare_android.engine.worker;

import java.util.Collection;

import cn.edu.xjtu.android.emoji_warfare_android.engine.BaseEngine;
import cn.edu.xjtu.android.emoji_warfare_android.engine.SyncLinkedList;
import cn.edu.xjtu.android.emoji_warfare_android.engine.entity.Entity;
import cn.edu.xjtu.android.emoji_warfare_android.engine.entity.MovableEntity;

/**
 * MoveWorker<br>
 * 移动处理器，用于替代旧的物理引擎中的移动对象模块<br>
 * 主要用法：<br>
 * 1.将物理边界传入构造器<br>
 * 2.将物理时间间隔(两次移动之间的间隔)传入构造器或者使用默认<br>
 * 3.将需要移动的对象使用add或者addAll加入移动处理器<br>
 * 4.覆写可移动对象的move方法，返回值为是否在移动完该实体后永久忽略(删除)该实体<br>
 * 5.根据需要设置回调(暂时没有需要设置的回调)<br>
 * 6.使用resume方法启动移动处理器<br>
 * 注意：<br>
 * 第4条中所说的“删除”是仅仅在移动处理器对象列表中删除，不会对其他处理器造成影响
 * 
 * @author bill
 *
 */
public class MoveWorker extends BaseWorker {
    /**
     * 默认两次移动之间的时间间隔
     */
    public final static long DEFAULT_MOVE_INTERVAL = 10;
    /**
     * 物理边界<br>
     * 用于在实体超出范围时自动删除
     */
    private final Entity physicsBoundary;
    /**
     * 需要移动的对象，所有的可移动对象。
     */
    private SyncLinkedList<MovableEntity> mEntities;

    /**
     * 构建一个移动处理器
     * @param engine
     *            引擎
     * @param physicsBoundary
     *            物理边界
     * @param interval
     *            移动时间间隔
     */
    public MoveWorker(BaseEngine engine, Entity physicsBoundary, long interval) {
        super(engine, interval);
        if (physicsBoundary == null) {
            throw new IllegalArgumentException("Physics boundary can't be null");
        }
        this.physicsBoundary = physicsBoundary;
        this.mEntities = new SyncLinkedList<MovableEntity>();
    }

    /**
     * 构建一个移动处理器，使用默认时间间隔
     * @param engine
     *            引擎
     * @param physicsBoundary
     *            物理边界
     */
    public MoveWorker(BaseEngine engine, Entity physicsBoundary) {
        this(engine, physicsBoundary, DEFAULT_MOVE_INTERVAL);
    }

    /**
     * 执行一帧移动
     */
    @Override
    public void run() {
        // 遍历所有的可移动对象
        for (int i = 0; i < mEntities.size(); i++) {
            MovableEntity e = mEntities.get(i);
            // 如果超出物理边界或者移动结果要求删除，则删除该实体
            if (physicsBoundary.isOverlap(e)) {
                if (e.move()) {
                    mEntities.remove(e);
                }
            } else {
                mEntities.remove(e);
            }
        }
    }

    /**
     * 向移动处理器中添加一个需要移动的实体
     * 
     * @param e
     *            目标可移动实体
     * @return always true
     */
    public boolean add(MovableEntity e) {
        return mEntities.add(e);
    }

    /**
     * 向移动处理器中添加所有需要移动的实体
     * 
     * @param cols
     *            可移动实体Collection，包括数组或其他Collection
     * @return true if it is modified, false otherwise.
     */
    public boolean addAll(Collection<? extends MovableEntity> cols) {
        return mEntities.addAll(cols);
    }

}
